package com.baitiaojun.moments.support;

import com.baitiaojun.api.exception.ConditionException;
import com.baitiaojun.api.util.AESUtil;
import com.baitiaojun.api.util.FileUtil;
import com.baitiaojun.api.util.HttpUtil;
import com.baitiaojun.moments.config.AsyncConfig;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

/**
 * @类名 FastDFSHandler
 * @作者 白条君
 * @创建日期 2023/1/27 20:03
 * @版本 1.0
 */
@Component
public class FastDFSSupport {

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private AsyncConfig asyncConfig;

    @Value("${fdfs.host}")
    private String host;

    @Value("${fdfs.port}")
    private String port;

    public String upload(MultipartFile file, String group) throws ConditionException, IOException {
        String type = FileUtil.getType(file);
        StorePath storePath = fastFileStorageClient.uploadFile(group, file.getInputStream(), file.getSize(), type);
        return storePath.getFullPath();
    }

    public List<String> batchUpload(MultipartFile[] files, String group) throws Exception {
        List<String> pathList = new ArrayList<>();
        int length = files.length;
        if (length > 0) {
            Executor executor = asyncConfig.getAsyncExecutor();
            if (ObjectUtils.isEmpty(executor)) {
                throw new ConditionException("无法获取线程池");
            }
            CyclicBarrier barrier = new CyclicBarrier(length + 1);
            AESUtil aesUtil = AESUtil.lazyGetAesUtil();
            for (MultipartFile file : files) {
                executor.execute(() -> {
                    try {
                        String path = this.upload(file, group);
                        if (StringUtils.isNotEmpty(path)) {
                            pathList.add(aesUtil.encrypt(path));
                        }
                        barrier.await(2, TimeUnit.MINUTES);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
            barrier.await();
        }
        return pathList;
    }

    public void getMomentsPictures(HttpServletRequest request, HttpServletResponse response, String filePath) throws Exception {
        if (StringUtils.isEmpty(filePath)) {
            throw new ConditionException("参数异常");
        }
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        String decryptPath = aesUtil.decrypt(filePath.replace(" ", "+"));
        Map<String, String> filePathMap = FileUtil.splitFilePath(decryptPath);
        String group = filePathMap.get("group").trim();
        String storagePath = filePathMap.get("filePath");
        StringBuilder urlStr = new StringBuilder("http://");
        urlStr.append(host).append(":").append(port).append("/").append(group).append("/").append(storagePath);
        String url = urlStr.toString();
        //获取请求头参数的名称列表进行遍历，然后把参数名称对应的值添加到一个map中
        Map<String,Object> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        String headerName;
        while (headerNames.hasMoreElements()) {
            headerName = headerNames.nextElement();
            headers.put(headerName, request.getHeader(headerName));
        }
        //通过获取FIleInfo得到总文件大小
        long fileSize = fastFileStorageClient.queryFileInfo(group, storagePath).getFileSize();
        //	2、accept-range：bytes
        //	3、content-type：image/jpeg
        response.setHeader("Accept-Ranges", "bytes");
        response.setContentLength((int) fileSize);
        //使用httputil的get方法得到outputstream进行输出，参数为map、response、url
        HttpUtil.get(url, headers, response);
    }
}
